home *** CD-ROM | disk | FTP | other *** search
- /* os_mac_eKeys.c
- * 3May92 e
- */
-
- #include "os_mac_eEdit.h"
-
- /* extensions to an editor for text files by e
- questions/comments via Internet <e@Flavors.COM> */
- /* Copyright © e, 1989,1992. All rights reserved.
- Developed using THINK C 5.0.1 for use with Gambit Scheme.
- This code may be freely distributed as long as this notice remains.
- balance_bwd was written by Marc Feeley.
- */
-
- #define graphic_char(c) (!(((c)>=0) && ((c)<=32)))
-
- static long whsp_fwd_guts( eRec **hE, long offs )
- {
- register char *text = *((**hE).hText);
- register char *p = text + offs;
- register char *end = text + eTeTextLength( hE );
- register char c;
-
- while( p < end )
- { c = *p++;
- if( graphic_char(c) )
- { if( c != ';' )
- return p - text - 1;
- else
- while ( p < end && *p++ != '\r' ) ;
- }
- }
- return end - text;
- }
-
- static long whsp_fwd( eRec **hE )
- {
- long offs = eTeChPosToOffset( hE, (**hE).selActive ? (**hE).selEnd : (**hE).caretChPos );
- return whsp_fwd_guts( hE, offs );
- }
-
- static long whsp_bwd( eRec **hE )
- {
- long offs = eTeChPosToOffset( hE, (**hE).selActive ? (**hE).selStart : (**hE).caretChPos );
- register char *text = *((**hE).hText);
- register char *p = text + offs - 1;
- register char c;
-
- while( p >= text )
- { if( graphic_char( *p ) )
- return p - text + 1;
- else
- p--;
- }
- return 0;
- }
-
- long balance_fwd_guts( eRec **hE, long offs, int bal )
- {
- register char *text = *((**hE).hText);
- register char *p = text + offs;
- register char *end = text + eTeTextLength( hE );
- register int b = bal;
- register char c;
-
- while( p < end && !graphic_char(*p) ) p++;
-
- while( p < end )
- { c = *p++;
- if( graphic_char(c) )
- switch (c)
- { case '(':
- b++;
- break;
- case ')':
- b--;
- if (b <= 0) goto scan_done;
- break;
- case ';':
- while ( p < end && *p++ != '\r' ) ;
- break;
- case '"':
- { while (p<end)
- { c = *p++;
- if( c == '"' ) goto breake;
- if( c == '\\' ) p++;
- }
- return -1;
- breake:
- if( b <= 0 ) goto scan_done;
- break;
- }
- case '#':
- if( *p == '\\' ) p += 2;
- break;
- case ',':
- if( *p == '@' ) p++;
- break;
- case '\'':
- case '`':
- break;
- default:
- { while ((p<=end) && graphic_char(c) && (c!='(') && (c!=')') && (c!='"'))
- c = *p++;
- p--;
- if (b <= 0) goto scan_done;
- break;
- }
- }
- }
- return -1;
-
- scan_done:
- return p-text;
- }
-
- long balance_fwd( eRec **hE, int bal )
- {
- long offs = eTeChPosToOffset( hE, (**hE).selActive ? (**hE).selEnd : (**hE).caretChPos );
- return balance_fwd_guts( hE, offs, bal );
- }
-
- static long balance_bwd_guts( eRec **hE, long offs, int bal, int prefix )
- {
- register char *text = *((**hE).hText);
- register char *p = text + offs;
- register int b = bal;
-
- while ((p>text) && !graphic_char(p[-1])) p--;
-
- while (p>text)
- if ((p>=text+3) && (p[-2]=='\\') && (p[-3]=='#'))
- { p -= 3;
- if (b <= 0) goto scan_prefix;
- }
- else
- { register char c = *--p;
- if (graphic_char(c))
- switch (c)
- { case '(':
- b--;
- if (b <= 0) goto scan_prefix;
- break;
- case ')':
- b++;
- break;
- case '"':
- { while (p>text)
- { register char *q = --p;
- while ((q>text) && (q[-1]=='\\')) q--;
- if ((p-q)&1L)
- p = q;
- else if (*p=='"')
- if (b <= 0) goto scan_prefix; else goto brak;
- }
- return -1;
- brak:
- break;
- }
- default:
- { while ((p>=text) && graphic_char(c) &&
- (c!='(') && (c!=')') && (c!='"'))
- c = *--p;
- p++;
- if (b <= 0) goto scan_prefix;
- break;
- }
- }
- }
- return -1;
-
- scan_prefix:
- if (prefix)
- while (p>text)
- { register char c = *--p;
- if ((c!='\'') && (c!='`') && (c!=',') && (c!='@') && (c!='#'))
- { p++; break; }
- }
- return p-text;
- }
-
- long balance_bwd( eRec **hE, int bal, int prefix )
- {
- long offs = eTeChPosToOffset( hE, (**hE).selActive ? (**hE).selStart : (**hE).caretChPos );
- return balance_bwd_guts( hE, offs, bal, prefix );
- }
-
- static int rangeBalance( register char *beg, register char *end )
- {
- register int n = 0;
-
- while(beg < end)
- { if (*beg == '(') n++;
- else if (*beg == ')') n--;
- beg++;
- }
- return(n);
- }
-
- /* 23Jul92 e */
-
- extern int check_TEInsert( char *ptr, long len, eRec **hE, int bold );
-
- #if 0
-
- /* 17Aug92 e */
-
- void eTabCommand( eRec **hE, short modifiers, short style )
- { long open_paren;
- long selStart, selEnd, selLen;
- ChPos solcp, eolcp;
- char *p;
- long sol, eol;
- long adj = 0;
- Boolean selActive;
-
- if( ( selActive = (**hE).selActive ) )
- { selStart = eTeChPosToOffset( hE, (**hE).selStart );
- selEnd = eTeChPosToOffset( hE, (**hE).selEnd );
- selLen = selEnd - selStart;
- eTeSetSelect( hE, selStart, selStart );
- solcp = (**hE).selStart;
- }
- else
- { selStart = eTeChPosToOffset( hE, (**hE).caretChPos );
- selLen = 0;
- solcp = (**hE).caretChPos;
- }
- eolcp.h = solcp.h = 0; /* start of line */
- eolcp.v = solcp.v + 1;
- eol = eTeChPosToOffset( hE, eolcp ); /* next line */
- sol = eTeChPosToOffset( hE, solcp ); /* this line */
- p = *((**hE).hText) + sol;
- while( ! graphic_char( *p ) && sol < eol && *p != RETURN ) { p++; sol++; solcp.h++; }
- if( sol != selStart ) eTeSetSelect( hE, sol, sol );
- if( sol < selStart ) adj = selStart - sol;
-
- open_paren = balance_bwd( hE, 0, 1 );
- eolcp = eTeOffsetToChPos( hE, open_paren );
- if( solcp.h > eolcp.h )
- { eolcp.v = solcp.v;
- eol = eTeChPosToOffset( hE, eolcp );
- eTeSetSelect( hE, eol, eol );
- eTeKillTo( hE, solcp );
- }
- else while (solcp.h < eolcp.h)
- { long len = (eolcp.h - solcp.h < 80) ? eolcp.h - solcp.h : 80;
- if (check_TEInsert( " ",
- len, hE, style )) goto err;
- solcp.h += len;
- }
- err:
- if( sol < selStart || selActive )
- { selStart = eTeChPosToOffset( hE, (**hE).caretChPos ) + adj;
- eTeSetSelect( hE, selStart, selStart + selLen );
- }
- eTeShowCaret( hE );
- }
-
- #else
-
- /* 14Oct92 e */
-
- static char dncase( char c )
- { if( c >= 'A' && c <= 'Z' ) return c + 0x20;
- else return c;
- }
-
- static Boolean eq_subfs( char *p, char *q )
- { char c;
- while( c = *p++ )
- if( c != dncase( *q++ ) )
- return FALSE;
- c = *q;
- return( ( graphic_char(c) && c != '(' && c != '"' ) ? FALSE : TRUE );
- }
-
- /* subforms of forms whose car is in this table are indented specially...
- call the subform to be indented "the target":
- if there are more than cnt subforms between the car and the target,
- then the last subform before the target determines the postion of the target,
- otherwise the target is indented one more space than the car
- */
-
- struct _spec_subfs { char *str; char cnt; };
-
- static struct _spec_subfs spec_subfs_data[] =
- { { "if", 1 },
- { "do", 2 },
- { "do*", 2 },
- { "let", 18 }, /* special case for named let */
- { "let*", 1 },
- { "case", 1 },
- { "begin", 0 },
- { "lambda", 1 },
- { "letrec", 1 },
- { "define", 1 },
- { "##declare", 0 },
- { "##define-macro", 1 },
- { "", -1 }
- };
-
- static long spec_subfs( char *p )
- { char c;
- long res = -1;
- struct _spec_subfs *s = spec_subfs_data;
- if( (c = dncase(*p)) >= 'a' && c <= 'z' )
- while( (res = (*s).cnt) >= 0 )
- if( eq_subfs( (*s).str, p ) )
- break;
- else
- s++;
- return res;
- }
-
- void eTabCommand( eRec **hE, short modifiers, short style )
- { long open_paren, upen_paren;
- long selStart, selEnd, selLen;
- ChPos solcp, eolcp;
- char *p;
- long sol, eol;
- long adj = 0;
- Boolean selActive;
-
- if( ( selActive = (**hE).selActive ) )
- { selStart = eTeChPosToOffset( hE, (**hE).selStart );
- selEnd = eTeChPosToOffset( hE, (**hE).selEnd );
- selLen = selEnd - selStart;
- eTeSetSelect( hE, selStart, selStart );
- solcp = (**hE).selStart;
- }
- else
- { selStart = eTeChPosToOffset( hE, (**hE).caretChPos );
- selLen = 0;
- solcp = (**hE).caretChPos;
- }
- eolcp.h = solcp.h = 0; /* start of line */
- eolcp.v = solcp.v + 1;
- eol = eTeChPosToOffset( hE, eolcp ); /* next line */
- sol = eTeChPosToOffset( hE, solcp ); /* this line */
- p = *((**hE).hText) + sol;
- while( ! graphic_char( *p ) && sol < eol && *p != RETURN ) { p++; sol++; solcp.h++; }
- if( sol != selStart ) eTeSetSelect( hE, sol, sol );
- if( sol < selStart ) adj = selStart - sol;
-
- open_paren = balance_bwd_guts( hE, sol, 0, 1 );
- /* 14Oct92 e */
- if( open_paren > 0 )
- { upen_paren = balance_bwd_guts( hE, sol, 1, 1 );
- if( upen_paren < 0 )
- { /* a toplevel form should be at column zero !? */
- eolcp.h = 0;
- goto justdotab;
- }
- else
- { long rover, prevr, first;
- long count = 0;
- char *text = *((**hE).hText);
- p = text + upen_paren;
- while( *p != '(' ) p++; /* there must be a '(' since upen_paren >= 0 */
- upen_paren = p - text; /* the offset of the '(' */
- prevr = upen_paren + 1;
- rover = first = whsp_fwd_guts( hE, prevr );
- while( rover > 0 && rover < open_paren )
- { prevr = rover;
- count++;
- rover = balance_fwd_guts( hE, rover, 0 );
- if( rover > 0 ) rover = whsp_fwd_guts( hE, rover );
- }
- /* now...
- upen_paren = start of enclosing form
- open_paren = start of preceeding form
- first = first sub-form of enclosing form
- prevr = last sub-form of enclosing form <= open_paren, or upen_paren+1 if none
- rover = last sub-form of enclosing form >= open_paren, or -1 if none
- count = position of rover in subforms of enclosing form
- */ /* this catches subforms inside comments... */
- if( rover != open_paren ) { open_paren = prevr; count--; }
- /* this handles special indentation for special forms... */
- if( first < sol
- && (rover = spec_subfs( text + first ) ) >= 0
- && ( count == 0 || count == rover || ( rover > 15 && count <= (rover&15)) ) )
- { eolcp = eTeOffsetToChPos( hE, first );
- eolcp.h += 1;
- goto justdotab;
- }
- }
- }
- /* */
- eolcp = eTeOffsetToChPos( hE, open_paren );
- justdotab:
- if( solcp.h > eolcp.h )
- { eolcp.v = solcp.v;
- eol = eTeChPosToOffset( hE, eolcp );
- /* 27Jan93 e -- this mungs the scrap...
- eTeSetSelect( hE, eol, eol );
- eTeKillTo( hE, solcp );
- instead... */
- eTeSetSelect( hE, eol, sol );
- eTeDelete( hE );
- }
- else while (solcp.h < eolcp.h)
- { long len = (eolcp.h - solcp.h < 80) ? eolcp.h - solcp.h : 80;
- if (check_TEInsert( " ",
- len, hE, style )) goto err;
- solcp.h += len;
- }
- err:
- if( sol < selStart || selActive )
- { selStart = eTeChPosToOffset( hE, (**hE).caretChPos ) + adj;
- eTeSetSelect( hE, selStart, selStart + selLen );
- }
- eTeShowCaret( hE );
- }
-
- #endif
-
- #define mCheck(n, ch) ((rover[n] == ch) && (n >= 0) && (n < teLength))
-
- void eEditCommand( eRec **hE, char ch, short modifiers, short style )
- {
- register char *rover;
- register long needLeft, needRight;
- long selStart, selEnd, teLength;
- short wanted; /* -1 at start, 0 range, 1 at end */
- Boolean selActive;
- short optioned = modifiers & optionKey;
- short shifted = modifiers & shiftKey;
-
- ch += 0x40; /* undo control key */
- modifiers &= ~controlKey;
-
- if( ( selActive = (**hE).selActive ) )
- { selStart = eTeChPosToOffset( hE, (**hE).selStart );
- selEnd = eTeChPosToOffset( hE, (**hE).selEnd );
- }
- else
- { selEnd = selStart = eTeChPosToOffset( hE, (**hE).caretChPos );
- }
- teLength = eTeTextLength( hE );
-
- rover = (char *)*(**hE).hText;
- wanted = 0; /* always range; someday use mark */
- needLeft = needRight = 0;
-
- switch( ch )
- {
- case 'T': /* Transpose */ /* 22Jul92 e */
- case 't':
- case '†': /* option-t */
- case 'ˇ': /* option-shift-t */
- if( selActive )
- SysBeep(6);
- else if( optioned )
- { needLeft = balance_bwd( hE, 0, 1 );
- needRight = balance_fwd( hE, 0 );
- if( needLeft >= 0 && needRight >= 0 )
- eTeTranspose( hE, needLeft, whsp_bwd( hE ), whsp_fwd( hE ), needRight );
- else
- SysBeep(6); /* can't be done! */
- }
- else
- eTeTranspose( hE, selStart - 1, selStart, selStart, selStart + 1 );
- return;
-
- case 'K': /* Kill */
- case 'k':
- case '': /* option-k */
- case '˚': /* option-shift-k */
- if( ! selActive && optioned )
- { /* c-m-k (del-fwd-sexp) */
- selEnd = balance_fwd( hE, 0 );
- if( selEnd >= 0 )
- { eTeKillTo( hE, eTeOffsetToChPos( hE, selEnd ) );
- }
- else SysBeep( 3 );
- }
- else /* Kill line */
- eTeKey( hE, 0x7f, KeyDel, optionKey, style);
- return;
-
- case 'D': /* Delete */
- case 'd':
- eTeKey( hE, 0x7f, KeyDel, 0, style);
- return;
-
- case 'O': /* Open line */
- case 'o':
- case 'ø': /* option-o */
- case 'Ø': /* option-shift-o */
- if( selActive )
- eTeSetSelect( hE, selStart, selStart );
- eTeKey( hE, '\r', 0, 0, style);
- eTeSetSelect( hE, selStart, selStart );
- return;
-
- case 'A':
- case 'a':
- case 'å': /* option-a */
- case 'Å': /* option-shift-a */
- if( optioned )
- { wanted = shifted ? 0 : -1;
- needLeft = 2;
- /* needRight = 2; */
- break;
- }
- eTeKey( hE, LEFT_ARROW, 0, modifiers | cmdKey, style );
- return;
-
- case 'E':
- case 'e':
- /* option-e is a dead key */
- case '´': /* option-shift-e */
- if( optioned )
- { wanted = shifted ? 0 : 1;
- /* needLeft = 2; */
- needRight = 2;
- break;
- }
- eTeKey( hE, RIGHT_ARROW, 0, modifiers | cmdKey, style );
- return;
-
- case 'P': /* Previous */
- case 'p':
- case 'π': /* option-p */
- case '∏': /* option-shift-p */
- eTeKey( hE, UP_ARROW, 0, modifiers, style );
- return;
-
- case 'N': /* Next */
- case 'n':
- /* option-n is a dead key */
- case '˜': /* option-shift-n */
- eTeKey( hE, DOWN_ARROW, 0, modifiers, style );
- return;
-
- case 'M': /* Match (Balance) */
- case 'm':
- case 'µ': /* option-m */
- case 'Â': /* option-shift-m */
- if( ! selActive )
- { /* too smart? 22Jul92 e
- if( mCheck( selStart, '(' ) )
- { selEnd = selStart + 1;
- needLeft = 0;
- needRight = 1;
- }
- else if( mCheck( selStart - 1, ')' ) )
- { selStart = selEnd - 1;
- needLeft = 1;
- needRight = 0;
- }
- else
- { needLeft = 1;
- needRight = 1;
- }
- */
- needLeft = 2;
- needRight = 2;
- }
- else
- { needRight = rangeBalance( &rover[selStart], &rover[selEnd] );
- /* too smart? 22Jul92 e
- if( needRight == 0 )
- { needLeft = 1;
- needRight = 1;
- }
- else if( needRight < 0 )
- { needLeft = -needRight;
- if( mCheck(selEnd - 1, ')' ) )
- needRight = 0;
- else
- { needRight = 1;
- needLeft += 1;
- }
- }
- else
- { if( mCheck( selStart, '(' ) )
- needLeft = 0;
- else
- { needLeft = 1;
- needRight += 1;
- }
- }
- */
- if( needRight == 0 )
- { needLeft = 2;
- needRight = 2;
- }
- else if( needRight < 0 )
- { needLeft = -needRight;
- needRight = 2;
- needLeft += 2;
- }
- else
- { needLeft = 2;
- needRight += 2;
- }
- }
- break;
-
- case 'ƒ': /* option f */ /* Forward */
- case 'f':
- case 'Ï': /* option shift f */
- case 'F':
- wanted = shifted ? 0 : 1;
- if( ! selActive || shifted )
- { if( optioned ) needRight = 1;
- else
- { eTeKey( hE, RIGHT_ARROW, 0, modifiers, style );
- return;
- }
- }
- /* else selection range case automatic */
- break;
-
- case '∫': /* option b */ /* Back */
- case 'b':
- case 'ı': /* option shift b */
- case 'B':
- wanted = shifted ? 0 : -1;
- if( ! selActive || shifted )
- { if( optioned ) needLeft = 1;
- else
- { eTeKey( hE, LEFT_ARROW, 0, modifiers, style );
- return;
- }
- }
- /* else selection range case automatic */
- break;
-
- default:
- return;
- }
- if( needRight != 0 )
- { selEnd = balance_fwd( hE, needRight - 1 );
- if( selEnd < 0 ) { SysBeep(6); return; } /* can't be done! */
- }
- if( needLeft != 0 )
- { selStart = balance_bwd( hE, needLeft - 1, 1 );
- if( selStart < 0 ) { SysBeep(6); return; } /* can't be done! */
- }
- eTeSetSelect( hE,
- (wanted == 1) ? selEnd : selStart,
- (wanted == -1) ? selStart : selEnd );
- eTeShowCaret( hE );
- }
-
- /* end of os_mac_eKeys.c */
-